home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / ctut.arc / LESSON6 < prev    next >
Text File  |  1986-02-07  |  24KB  |  668 lines

  1. .NT
  2.  A NOTE ABOUT THE LESSONS in C 
  3. .b4-24
  4. .R5C4
  5. These were written while the author was ~Ilearning~N  the language and since
  6. .R6C4
  7. they  are  ~Ifree~N ( to  copy  and/or  distribute ) there  is  a money-back
  8. .R7C4
  9. guarantee on the accuracy of each and every statement in the lessons (!)
  10. .R9C4
  11. The  ~Idisplay~N  program was written ( in C ) in order to provide a vehicle
  12. .R10C4
  13. for displaying the lessons.
  14. .R12C5
  15. .B
  16. P.J.Ponzo
  17. .B
  18. Dept. of Applied Math
  19. .B
  20. Univ. of Waterloo
  21. .B
  22. Ontario N2L 3G1
  23. .K16,30
  24. PonzoTUTOR
  25. .WNT
  26.   POINTERS and ARRAYS  
  27. .R4C1
  28.     Recall that, when we refer to ~b~I&x~N, ~IC~N will interpret this as the
  29.     ~Iaddress~N in memory of the variable ~b~Ix~N. Here ~b~I&x~N is a ~w~Rpointer~N.
  30.  
  31.     If we set ~b~Iy=&x~N, in our program, then ~b~Iy~N ~w~Rpoints~N to the 
  32.     variable ~b~Ix~N  ( ~b~Iy~N is now an address, in memory ).
  33.  
  34. .b9-11
  35. .R10C17
  36. ~V    HOW DO WE DECLARE A POINTER VARIABLE ?    ~N
  37. .W
  38. .R10C17
  39. ~V                    patience                  ~N
  40.  
  41.     In addition to the ~b~I&~N ~Ioperator~N (which returns the ~Iaddress~N of
  42.     the variable which follows it), there is the C ~Ioperator~N ~b~I*~N.
  43.  
  44.     If ~b~Iy~N points to ~b~Iint x~N, then ~b~I*y~N is the ~Icontents of memory~N
  45.     ~Ilocation y~N. When a program refers to ~b~I*y~N, the C compiler will go
  46.     to the address given by the ~w~Rpointer~N ~b~Iy~N, extract the ~b~Iint~Neger
  47.     it finds there, and use this ~b~Iint~Neger in place of ~b~I*y~N.
  48.  
  49.     This poses a problem.....
  50. .K19,60
  51. a problem?
  52. .WN
  53.  
  54.     How is the compiler to know whether the contents of the address ~b~Iy~N,
  55.     (which we refer to as ~b~I*y~N, in our program) is an ~b~Iint~Neger or a
  56.     ~b~Ifloat~Ning point number or a ~b~Ichar~Nacter variable  ???
  57.  
  58.     Since an ~b~Iint~Neger occupies ~I2~N bytes ( usually ..depending upon the
  59.     computer you are using) and a single ~b~Ichar~Nacter variable occupies
  60.     just ~I1~N byte and a ~b~Ifloat~N occupies ~I4~N bytes ...etc. etc...then
  61.     it's clearly important that the compiler KNOW that ~b~Iy~N is pointing to
  62.     an ~b~Iint~N or a ~b~Ichar~N or a ~b~Ifloat~N ...etc.
  63.  
  64.    ~ISO ... we must declare the type of variable that ~b~Iy~N points to !~N
  65.  
  66.     To do this we declare ~Ithe contents of y~N, namely ~b~I*y~N !!
  67. .K19,60
  68.  example?
  69. .WN
  70. 1 ~b~Imain() {                                                    ~N
  71. 2 ~b~I    int *y;                                                 ~N
  72. 3 ~b~I    int x=123;                          /* x=integer 123  */~N
  73. 4 ~b~I    y=&x;                               /* y=address of x */~N
  74. 5 ~b~I    printf("The value of x is %d",*y);                      ~N
  75. 6 ~b~I}                                                           ~N
  76.     This program will (correctly) print: ~r~IThe value of x is 123~N
  77. .K19,60
  78.  int *y;
  79.  
  80.     Note that, in line 4, ~b~Iy~N is made a ~w~Rpointer~N, pointing to ~b~Ix~N
  81.     and ~b~Ix~N is an ~b~Iint~N .... ~ISO~N  ... in line 2 we declare our
  82.     ~w~Rpointer~N ~b~Iy~N as:  ~b~I  int *y  ~N  since it points to an ~b~Iint~N.
  83. .K19,60
  84. all clear?
  85. .WN
  86.  
  87.        ~V                                                        ~N
  88.        ~V   REMEMBER!! IF  sam  IS A POINTER TO SOME  VARIABLE,  ~N
  89.        ~V              THEN BE SURE TO DECLARE *sam AS THE SAME  ~N
  90.        ~V              TYPE AS THE VARIABLE TO WHICH sam POINTS! ~N
  91.        ~V                                                        ~N
  92. .b1-7
  93. .K19,32
  94. mamma mia!
  95. .R10C1
  96.     If ~b~Ix~N is an ~Iint~N  and ~b~Iy=&x~N then declare : ~b~Iint *y~N
  97.     If ~b~Ix~N is a  ~Ichar~N and ~b~Iy=&x~N then declare : ~b~Ichar *y~N
  98.     If ~b~Ix~N is a ~Ifloat~N and ~b~Iy=&x~N then declare : ~b~Ifloat *y~N
  99. .WNT
  100.    VARIABLES and their HOMES in MEMORY   
  101.     We've mentioned that the ~b~Ichar c~N occupies ~I1~N byte of memory, and 
  102.     that ~b~Iint i~N occupies ~I2~N bytes and ~b~Ifloat f~N occupies ~I4~N bytes.
  103.  
  104.     Suppose ~b~Ipc=&c~N is a ~w~Rpointer~N to ~b~Ic~N, and ~b~Ipi=&i~N and ~b~Ipf=&f~N.
  105.  
  106.         ~V  WHERE DOES pc+1 POINT TO ?  ~N
  107.  
  108.    and  ~V  WHERE DOES pi+1 POINT TO ?  ~N
  109.  
  110.    and  ~V  WHERE DOES pf+1 POINT TO ?  ~N
  111. .K16,32
  112. I give up!
  113. .WN
  114. .B
  115.     
  116. .B
  117.     
  118. .B
  119.     
  120. .B
  121.     
  122. .B
  123.     
  124. .B
  125.     
  126. .B
  127.     
  128. .B
  129.     
  130. .B
  131.     
  132. .B
  133.     
  134. .B
  135.     
  136. .B
  137.     
  138. .R4C2
  139. pc-2 pc-1 pc   pc+1 pc+2 pc+3 pc+4 pc+5 pc+6 pc+7 pc+8
  140.  
  141.  
  142.     If the boxes are each ~I1~N byte of memory, and ~b~Ipc~N points to one
  143.     such byte, then the scheme shown above indicates where ~b~Ipc-2~N, etc.
  144.     point to.
  145.  
  146.     The fact that ~b~Ipc~N is a ~w~Rpointer~N to a ~b~Ichar~N (because we would 
  147.     (should?) have declared it with ~b~Ichar *pc~N) and because a ~b~Ichar~N
  148.     only occupies ~I1~N byte, then ~IC~N is smart enough to know that ~b~Ipc-2~N
  149.     is the address of the memory location 2 bytes below ~b~Ipc~N.
  150. .K16,32
  151.  try int!
  152. .WN
  153. .B
  154.     
  155. .B
  156.     
  157. .B
  158.     
  159. .B
  160.     
  161. .B
  162.     
  163. .B
  164.     
  165. .B
  166.     
  167. .B
  168.     
  169. .B
  170.     
  171. .B
  172.     
  173. .B
  174.     
  175. .B
  176.     
  177. .R4C2
  178. pi-1       pi         pi+1       pi+2       pi+3       pi+4
  179.  
  180.     Now ~b~Ipi~N points to a (~I2~N byte) ~b~Iint~N, so ~IC~N (whatta guy!)
  181.     arranges that ~b~Ipi-1~N points ~I2~N bytes earlier than ~b~Ipi~N ...that
  182.     way it will point to the IMMEDIATELY PRECEDING ~b~Iint~N.
  183.  
  184.     (...of course, who knows if there IS an ~b~Iint~N stored at ~b~Ipc-1~N ?!)
  185. .W
  186. .K16,32
  187. TRY FLOAT!
  188. .WN
  189. .B
  190.     
  191. .B
  192.     
  193. .B
  194.     
  195. .B
  196.     
  197. .B
  198.     
  199. .B
  200.     
  201. .B
  202.     
  203. .B
  204.     
  205. .B
  206.     
  207. .B
  208.     
  209. .B
  210.     
  211. .B
  212.     
  213. .R4C2
  214.             pf                     pf+1                    pf+2
  215.  
  216.     You guessed it! ~b~Ipf+1~N will point to the VERY NEXT ~b~Ifloat~N, 
  217.     ~I4~N bytes past where ~b~Ipf~N points.
  218.  
  219.     (...ain't ~Iaddress arithmetic~N wonderful ? )
  220.  
  221.     NOTE:If we have ~b~Imain() {           ~N
  222.                     ~b~I    float f, *pf;  ~N
  223.                     ~b~I    f=12.3;        ~N
  224.                     ~b~I    pf=&f;         ~N
  225.  
  226.          then what IS ~I4~N bytes past the address of ~b~If~N ???
  227.  
  228.     There is one circumstance where we WILL know "what comes after".
  229. .K19,60
  230.   GUESS!
  231. .WNT
  232.     hip hip ARRAYS    
  233. .R4C1
  234.     You may recall, from an earlier lesson, that we defined a string by
  235.     declaring it to be an ARRAY of (single) ~b~Ichar~Nacters.
  236.  
  237.     We'll reproduce it here:
  238.  
  239. ~b~Ichar x[10];~N                 defines an ~IARRAY~N of ~b~I10~N elements.
  240. ~b~Ix[0]='A';~N                   the first element is the character ~b~IA~N.
  241. ~b~Ix[1]='b';~N                   the second element is the character ~b~Ib~N.
  242. ~b~Ix[2]='{';~N                   the third element is the character ~b~I{~N.
  243. ~b~Ix[3]='\0';~N                  the last element is the 'number' ~I0~N!!!!
  244. ~b~Iprintf("the string is %s",x);~N    print the string, up to the ~I0~N.
  245.  
  246.     ...and the printout would be: ~r~Ithe string is Ab{~N
  247. .K19,60
  248. remember?
  249. .WN
  250. ~b~Imain() {                          ~N
  251. ~b~I    char x[10], *px;              ~N
  252. ~b~I    x[0]='A';                     ~N
  253. ~b~I    x[1]='b';                     ~N
  254. ~b~I    x[2]='{';                     ~N
  255. ~b~I    x[3]='\0';                    ~N
  256. ~b~I    printf("the string is %s",x); ~N
  257.  
  258.  
  259.     NOW, if we define ~b~Ipx=&x[0]~N, a ~w~Rpointer~N to the first element in
  260.     the ARRAY ~b~Ix[]~N, then:
  261. .W
  262. .Q
  263. What character does px+2 point to ?
  264. {
  265. ~b~Iprintf("%c%c%c",*px,*(px+1),*(px+2));~N
  266. .Q
  267. What will the above print?
  268. Ab{
  269.  
  270.     ~b~Iprintf("%c",*px);~N would print the contents of memory location
  271.     ~b~Ipx~N, namely ~r~IA~N, and ~b~Iprintf("%c",*(px+1));~N prints ~r~Ib~N,
  272.     and ~b~Iprintf("%c",*(px+2));~N prints ~r~I{~N, and ALL THREE GIVE: ~r~IAb{~N.
  273.  
  274.                    ( ...a-a-a-h, C is ~Iso~N clever ...)
  275. .K2,60
  276. whatta gal
  277. .WN
  278. 1 ~b~I    char x[4];                    ~N
  279. 2 ~b~I    x[0]='A';                     ~N
  280. 3 ~b~I    x[1]='b';                     ~N
  281. 4 ~b~I    x[2]='{';                     ~N
  282. 5 ~b~I    x[3]='\0';                    ~N
  283.     In this program excerpt, we defined some elements of the ARRAY ~b~Ix[10]~N
  284.     by saying ( laboriously ):~b~Ix[0]='A'; x[1]='b'; x[2]='{'; x[3]='\0';~N  
  285.  
  286.     For a ~b~Ichar~N ARRAY we can also say:
  287.  
  288. ~b~Ichar x[4]={ 'A','b','{','\0' };~N
  289.  
  290.     making Lines 2-5 unnecessary.
  291.  
  292.     For an ~b~Iint~N ARRAY we can say:
  293.  
  294. ~b~Iint x[3]={11,12,13};~N
  295.  
  296.     Under certain conditions, all ARRAYS may be ~Iinitialized~N (defined as they
  297.     are declared).  We'll talk about this later ...
  298. .K10,60
  299.  curly {
  300. .WNT
  301.    More POINTERS and ARRAYS   
  302. .R4C1
  303.     When we define an ARRAY, say:  ~b~I int s[10];~N  then each of ~b~Is[0]~N,
  304.     ~b~Is[1]~N, etc are (~I2~N byte) ~b~Iint~Negers.
  305.  
  306.                    ~I...and here's something special:~N 
  307. .b6-8
  308. .R10C1
  309.                ~b~Is~N, all by itself, is a ~w~Rpointer~N to ~b~Is[0]~N
  310. .b9-11
  311. .K19,60
  312.   WHAT!
  313. .W
  314. .R12C1                                                           
  315. 1 ~b~Imain() {                                                     ~N
  316. 2 ~b~I    int s[3];                    /* define integer array  */ ~N
  317. 3 ~b~I    s[0]=11; s[1]=12; s[2]=13;   /* define members of s[] */ ~N
  318. 4 ~b~I    printf("%d",s[0]);           /* print first integer   */ ~N
  319. 5 ~b~I    printf("\n%d",*s);           /* print what s points to*/ ~N
  320. 6 ~b~I}                                                            ~N
  321.     Line 4 will print ~r~I11~N and line 5 will print ~r~I11~N    !!!
  322.     ..proving that s[0] and *s are the same, right?
  323.     ..so ~Is is a pointer to s[0]~N, right?
  324. .K19,60
  325. RIGHT!
  326. .W
  327.     Of course it would have been easier to say:
  328. 2 ~b~Iint s[3]={11,12,13};~N and omit Line 3!
  329. .WN
  330.     NOW, since an ARRAY (~Iany~N ARRAY, whether ~b~Iint~Ns or ~b~Ichar~Ns or ~b~Ifloats~N)
  331.     ~Vhas its name as a pointer~N (..think about that! ), then not only will ~b~Is[2]~N
  332.     give the 3rd element in the ARRAY, ~Ibut so will *(s+2) give the 3rd element!~N
  333.  
  334.     Here's a program you've seen in an earlier lesson (on STRINGS):
  335.  
  336. 1 ~b~Imain() {                                                     ~N
  337. 2 ~b~I    char s;                      /* declare a char        */ ~N
  338. 3 ~b~I    s="I am a string";           /* make it a string      */ ~N
  339. 4 ~b~I    printf("%s",s);              /* print the string      */ ~N
  340. 5 ~b~I    printf("\n%s",s+2);          /*       what ?????      */ ~N
  341. 6 ~b~I}                                                            ~N
  342.  
  343.     Line 2 declares ~b~Is~N to be of type ~b~Ichar~N.
  344.     Line 3 defines  ~b~Is~N to be a string ( double quotes, remember?).
  345.     Line 4 prints the ~b~I%s~Ntring, giving ~r~II am a string~N        
  346.     Line 5 prints ....  ~r~Iam a string~N
  347. .W
  348.  
  349.     Here, just as for an ARRAY, ~b~Is~N is a ~w~Rpointer~N to the string
  350.     ~b~I"I am a string"~N. In fact, ~b~Is~N points to the first element: ~b~II~N.
  351.     HENCE, ~b~Is+2~N points to the ~I3rd element~N (~b~Ia~N) and ~b~Iprintf()~N will
  352.     (upon receipt of a ~b~I%s~Ntring address) print everything from that
  353.     address up to the special terminating ~I'\0'~N   ( ...remember him?).
  354. .WK7,32
  355. magnifico!
  356. .WN
  357.  
  358.  
  359.  
  360.  
  361.  
  362.  
  363.  ~ITHE NAME OF A STRING VARIABLE IS A POINTER TO THE FIRST ELEMENT IN THE STRING!
  364.  
  365.  ~ITHE NAME OF AN ARRAY VARIABLE IS A POINTER TO THE FIRST ELEMENT IN THE ARRAY !
  366. .b5-11
  367. ~I
  368. .K16,32
  369. REMEMBER!
  370. .WR3C1
  371.                    ...and ~r~Ipointer~N arithmetic is wonderful...
  372. .b2-4
  373. .WNT
  374.   Be kind to your compiler  
  375. .R4C1
  376.     Now, if we declare ~b~Ichar a[30];~N the C-compiler knows that ~b~Ia~N refers
  377.     to a collection of ~I30~N ~b~Ichar~Ns ...and it knows this even before we define
  378.     the elements ~b~Ia[0]~N, ~b~Ia[1]~N, etc.
  379.  
  380.     BUT, if we declare ~b~Ichar s;~N, how is the compiler to know whether ~b~Is~N
  381.     if a single ~b~Ichar~N or a string of ~b~Ichar~Ns. If, subsequently, we say
  382.     ~b~Is="I am a string"~N then ~b~Is~N IS a string ..but if we say ~b~Is='A'~N
  383.     then ~b~Is~N is just one ~b~Ichar~N ...but should we REALLY make the compiler
  384.     figure this out? After all, the compiler would reserve a single byte in
  385.     memory for just one ~b~Ichar~N but may have to reserve dozens of bytes for
  386.     a string of ~b~Ichars~N!
  387.  
  388.     ~VMORAL~N:     DECLARE A SINGLE CHARACTER AS ~b~Ichar s;~N
  389.                DECLARE A STRING OF CHARS  AS ~b~Ichar *s;~N
  390. .b15-18
  391.  
  392.     Since we (and the compiler) know that the name of a string is a ~w~Rpointer~N
  393.     then the declaration ~b~Ichar *s;~N (followed perhaps by ~b~Is="I'm a string"~N)
  394.     just anticipates the subsequent use of ~b~Is~N as the name of a string (as
  395.     opposed to a single character).
  396. .WNR3
  397. ~b~I                         ~N
  398. ~b~I    char s;              ~N
  399. ~b~I    s="I am a string";   ~N
  400. ~b~I    printf("%s",s);      ~N
  401. ~b~I                         ~N
  402.  
  403.     Although we have used the above format in earlier lessons .....
  404.  
  405. .B
  406. IT MAY NOT COMPILE!
  407. .R14C1
  408.  ...and if it does 
  409.  
  410. .B
  411. IT MAY NOT WORK!  
  412. .WR4C40
  413. ~b~I    char *s;             ~N
  414. .R21B
  415.      If we use ~b~Ichar *s~N then ALL compilers will accept it.    
  416. .WN
  417.     We have:
  418.  
  419.     If ~b~Is~N is the name of a string (defined with ~Idouble quotes~N) then
  420.     ~b~Is~N ~b~Is+1~N ~b~Is+2~N etc ~w~Rpoint~N to the ~I1st~N ~I2nd~N ~I3rd~N etc.
  421.     members of the string.
  422. .b2-6 
  423. .R8C1
  424.     If ~b~Is~N is the name of an ARRAY (defined with ~b~Is[0]=...~N etc.) then
  425.     ~b~Is~N ~b~Is+1~N ~b~Is+2~N etc ~w~Rpoint~N to the ~I1st~N ~I2nd~N ~I3rd~N etc.
  426.     members of the ARRAY. 
  427. .b7-11 
  428. .K17,60
  429. hmmmmmm...
  430. .WN
  431.     Now, don't think that strings and ARRAYs are the same ...after all a string
  432.     is only an ~IARRAY of (single) ~bchar~N~I variables~N whereas we can also have
  433.     ARRAYs of ~b~Iint~Ns or ~b~Ifloats~N or other interesting ~Idata types~N.
  434. .W
  435.  
  436.     Further, the name of a string pointer is a VARIABLE:
  437.  
  438. 1 ~b~Imain()  {                                            ~N
  439. 2 ~b~I   char *x, *y, *z;   /* 3 pointers to strings    */ ~N
  440. 3 ~b~I   x="ABC";           /* x points to string ABC   */ ~N
  441. 4 ~b~I   y="DEF";           /* y points to string DEF   */ ~N
  442. 5 ~b~I   z=x;               /* z points to string ABC   */ ~N
  443. 6 ~b~I   printf(" The x-string is %s",z);                  ~N
  444. 7 ~b~I   z=y;               /* z points to string DEF   */ ~N
  445. 8 ~b~I   printf(" The y-string is %s",z);                  ~N
  446. 9 ~b~I                                                     ~N
  447.     In line 5 we make ~b~Iz~N point to the same thing that ~b~Ix~N points to
  448.     ...and line 6 prints: ~r~I The x-string is ABC~N
  449.  
  450.     In line 7 we make ~b~Iz~N point to the same thing that ~b~Iy~N points to 
  451.     ...and line 8 prints: ~r~I The y-string is DEF~N
  452. .W
  453.     BUT, we could also say: ~b~Ix=y;~N and make ~b~Ix~N point to the y-string!
  454. .WNT
  455.     STRINGS and 1-dimensional CHAR ARRAYS   
  456. .R4C1
  457.     Suppose we may declare strings ~b~Ic~N and ~b~Ix~N by using:
  458.  
  459.     1   ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'}; ~N 
  460.     2   ~b~Ichar *x="x-string";                               ~N
  461.  
  462.     In the first instance, ~b~Ic~N is a ~r~Ipointer~N to an ARRAY of ~b~Ichar~Nacter
  463.     variables (8 ~b~Ichar~Ns: ~Ic-string~N , plus the terminating '\0').
  464.  
  465.     In the second instance, ~b~Ix~N is ~Ialso~N a ~r~Ipointer~N, but now it's a
  466.     ~r~Ipointer~N to a ~Istring~N: ~b~Ix-string~N with (again) the terminating
  467.     '\0' (which ~IC~N looks after appending).
  468.  
  469.     SO WHAT'S THE DIFFERENCE BETWEEN    char c[]   and   char *x ???
  470. .K19,60
  471. I give up
  472. .WN
  473.     1   ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'}; ~N 
  474.     2   ~b~Ichar *x="x-string";                               ~N
  475.  
  476.     In the first case, ~b~Ic~N is a ~ICONSTANT POINTER~N to the first element of
  477.     the ARRAY ...and ~Icannot be changed~N.
  478.     In the second case, ~b~Ix~N is a ~IVARIABLE POINTER~N to the first element of
  479.     the string ...and ~ICAN~N be changed!
  480. .K19,32
  481.   WHAT!
  482. .WN
  483. 1 ~b~Ichar c[9]={'c','-','s','t','r','i','n','g','\0'};               ~N 
  484. 2 ~b~Ichar *x="x-string";                                             ~N
  485. 3 ~b~Iprintf("  %s   %s ",c,x);     /* print %strings  c and x    */  ~N
  486. 4 ~b~Ix=c;                          /* make x point to c          */  ~N
  487. 5 ~b~Iprintf("  %s   %s ",c,x);     /* print %strings  c and x    */  ~N
  488.  
  489.     Just to show that it is ~b~Ix~N (and ~INOT~N ~b~Ic~N) which is a VARIABLE,
  490.     we declare/define them both in Lines 1 and 2.
  491.     Then print them both in Line 3. We would get:
  492.  
  493. ~r~I  c-string   x-string~N
  494.  
  495.     Then we ~Ichange x~N, in Line 4, so it points to the same thing as ~b~Ic~N does,
  496.     then print them both again, in Line 5. We'd get:
  497.  
  498. ~r~I  c-string   c-string~N
  499.  
  500.     You must not try:  ~b~Ic=x;~N    because it won't compile!
  501.  
  502.     ARRAY names point (ALWAYS and FOREVER) to the first element of the ARRAY!
  503. .b19-21
  504. .WNT
  505.    more and more ARRAYS   
  506. .R4C1
  507.     In addition to an ARRAY such as ~b~Ix[10]~N (with 10 elements,
  508.     which may be char,int,float,etc.),here's a ~Idouble ARRAY~N:
  509.  
  510. ~b~Ifloat x[5][7];~N   This declares an ARRAY of 5*7=~I35~N
  511.                  floating point numbers. We may define any or all
  512.                  of them (for example we may write ~b~Ix[2][1]=1.5~N).
  513.                  We think of this ARRAY as being arranged like so:
  514. .R12C1
  515.            x[0][0] x[0][1] x[0][2] x[0][3] x[0][4] x[0][5] x[0][6]
  516.            x[1][0] x[1][1] x[1][2] x[1][3] x[1][4] x[1][5] x[1][6]
  517.            x[2][0] x[2][1] x[2][2] x[2][3] x[2][4] x[2][5] x[2][6]
  518.            x[3][0] x[3][1] x[3][2] x[3][3] x[3][4] x[3][5] x[3][6]
  519.            x[4][0] x[4][1] x[4][2] x[4][3] x[4][4] x[4][5] x[4][6]
  520. .b11-17
  521. .K4,66
  522. x[i][j][k]
  523. .WR4C1
  524.                                                                               
  525.                                                                               
  526.                                                                               
  527.                                                                               
  528.                                                                               
  529.                                                                               
  530.                                                                               
  531. .R4C1
  532.     Now, if we define ~b~Ix[2][1]=1.5~N, the number 1.5 goes here!
  533. .sR14C20
  534. ~Fx[2][1]~N
  535. .r
  536.  
  537.     ...and, as you might expect, we can have ~I3-dimensional~N ARRAYS, etc.
  538. .rK4,66
  539. x[i][j][k]
  540. .WN
  541. ~V  x[0][0] x[0][1] x[0][2] x[0][3] x[0][4] x[0][5] x[0][6]  ~N
  542. ~V  x[1][0] x[1][1] x[1][2] x[1][3] x[1][4] x[1][5] x[1][6]  ~N
  543. ~V  x[2][0] x[2][1] x[2][2] x[2][3] x[2][4] x[2][5] x[2][6]  ~N
  544. ~V  x[3][0] x[3][1] x[3][2] x[3][3] x[3][4] x[3][5] x[3][6]  ~N
  545. ~V  x[4][0] x[4][1] x[4][2] x[4][3] x[4][4] x[4][5] x[4][6]  ~N
  546.     When we declare a multi-dimensional ARRAY, as in ~b~Ifloat x[5][~F7~N~b~I]~N, the
  547.     C-compiler knows that each element occupies ~I4 bytes~N in memory (because
  548.     it's an ARRAY of ~b~Ifloat~Ns) ..hence it knows not only how much memory
  549.     is needed but where each element is. Starting at the ~Iaddress~N of the first
  550.     element, ~b~I&x[0][0]~N, we find the ~Iaddress~N of ~b~Ix[~F2~N~b~I][~F1~N~b~I]~N by moving
  551.     ~F~I7~N*~F~I2~N+~F~I1~N=15 elements along the ARRAY ...and at 4-bytes-per-element
  552.     that means moving 4*15=60 bytes through memory.
  553.  
  554.     Notice how important the number of ~Icolumns~N is to the C-compiler (in the
  555.     declaration ~b~Ifloat x[5][7]~N
  556.     Without this dimension the compiler wouldn't know how to get to ~b~Ix[2][1]~N!
  557.  
  558.     In fact, ~IYOU MAY LEAVE OUT THE NUMBER OF ROWS IN DECLARING THIS ARRAY!~N
  559.  
  560.     (and use ~b~Ifloat x[][7]~N instead!)
  561. .WR6C1s
  562.                                                                               
  563.                                                                               
  564.                                                                               
  565.                                                                               
  566.                                                                               
  567.                                                                               
  568.                                                                               
  569.                                                                               
  570.                                                                               
  571.                                                                               
  572.                                                                               
  573.                                                                               
  574.                                                                               
  575.                                                                               
  576.                                                                               
  577. .r
  578.     A 2-dimensional ARRAY is treated (by ~IC~N) as a 1-dimensional ARRAY each
  579.     of whose elements is a 1-dimensional ARRAY.
  580.  
  581.     The ARRAY ~b~Ifloat x[5][7]~N consists of ~I5~N 1-dimensional ARRAYS, called
  582.     (in C-speak), ~b~Ix[0]~N, ~b~Ix[1]~N, ~b~Ix[2]~N, etc. and each of these
  583.     1-dimensional ARRAYS has ~I7~N elements.
  584.  
  585.     Since (for example) the element 3  of an ARRAY ~b~Isam~N is called ~b~Isam[3]~N
  586.     then element 3 of the (1-dimensional) ARRAY ~b~Ix[2]~N is called ~b~Ix[2][3]~N
  587.     ... which explains the C-notation for 2-dimensional ARRAYS,
  588.     x[i][j], rather than (the more usual) x[i,j].
  589.  
  590.     In fact, you may refer to ~b~Ix[2][3]~N as ~b~I(x[2])[3]~N ... meaning 
  591.     element 3 of the (1-dimensional) ARRAY x[2] (actually the 4th element
  592.     since the first is element 0 !!!@#$*).
  593. .WR3C1
  594. ~V  x[2][0] x[2][1] x[2][2] ~Fx[2][3]~N~V x[2][4] x[2][5] x[2][6]  ~N
  595. .WN
  596.  
  597.  
  598.     If ~IC~N regards ~b~Ix[5][7]~N as consisting of ~I5~N 1-dimensional ARRAYS
  599.     ~b~Ix[0]~N, ~b~Ix[1]~N, ~b~Ix[2]~N, ~b~Ix[3]~N, and ~b~Ix[4]~N then what
  600.     does (for example) ~b~Ix[2]~N refer to ?  What happens if we printf() ~b~Ix[2]~N?
  601.     Is ~b~Ix[2]~N just a notation or does it refer to one of the ~I5*7=35~N members
  602.     of ~b~Ix[5][7]~N ?
  603. .b2-8
  604. .K10,32
  605. I give up!
  606. .WN
  607.  
  608.     Actually, ~IC~N is very clever. ~b~Ix[2]~N (all by itself) is a ~r~Ipointer~N to the
  609.     first element in the 1-dimensional ARRAY ~b~Ix[2]~N, namely  ~b~Ix[2][0]~N !
  610.  
  611.     ~IREMEMBER~N: Although ~b~Ix[2][0]~N gives the ~Ivalue~N of element ~b~Ix[2][0]~N,
  612.               ~b~Ix[2]~N gives the ~Iaddress~N of ~b~Ix[2][0]~N!!
  613.  
  614.     Since ~b~Ix[2]~N is a ~r~Ipointer~N to ~b~Ix[2][0]~N, then ~Iaddress arithmetic~N
  615.     can be used to obtain the ~Iaddress~N of any element in the 1-dimensional
  616.     ARRAY ~b~Ix[2]~N.
  617.  
  618.     That means that we could identify the element ~b~Ix[i][j]~N
  619.     by pointing just ~Ij~N elements past the address of ~b~Ix[i][0]~N.
  620.  
  621.     That means that ~b~Ix[i]+j~N is a ~r~Ipointer~N to ~b~Ix[i][j]~N
  622.  
  623.     That means that the 'value' of this element is ~b~I*(x[i]+j)~N.
  624.  
  625.     ~IREMEMBER~N: If x[i]+j is a pointer, then *(x[i]+j) is what it points to!
  626. .b4-7
  627. .b18-20
  628. .WK8,32
  629. MAMMA MIA!
  630. .R23C1
  631.           ~Iand that means that *(x[2]+3) and x[2][3] are EQUIVALENT~N
  632. .b22-24
  633. .WNT
  634.     What's in a name ? (of an ARRAY)  
  635. .R6C1
  636.   ~V                                                                    ~N
  637.   ~V             The  name  of a  1-dimensional  ARRAY is a             ~N
  638.   ~V             POINTER to the first element of the ARRAY!             ~N
  639.   ~V                                                                    ~N
  640. .b5-10
  641.  
  642.     SO, if ~b~Ix~N is an ARRAY, declared as ~b~Iint x[10]~N, then ~b~Ix~N
  643.     is a ~r~Ipointer~N to ~b~Ix[0]~N (since ~b~Ix~N is 1-dimensional).
  644.  
  645.     AND, if ~b~Ix~N is an ARRAY, declared as ~b~Iint x[10][15]~N, then ~b~Ix[7]~N
  646.     is a ~r~Ipointer~N to ~b~Ix[7][0]~N (since ~b~Ix[7]~N is 1-dimensional).
  647. .K19,32
  648. sounds OK!
  649. .WN
  650. .R10C1
  651.     ...and finally, we may ~b~Iprintf("%d",x[7][2]);  ~N to print the value of
  652.  
  653.     the element, OR we may ~b~Iprintf("%d",*(x[7]+2));~N.
  654. .b8-14
  655. .K19,32
  656. beautiful!
  657. .WN
  658.  
  659.  
  660. .T
  661.    That's all folks!   
  662. .K16,32
  663. au revoir!
  664.  
  665.  
  666. .q
  667.  
  668.